#if !defined(_CNODO_H_)
#define _CNODO_H_

#include "Casillero.h"
#include "Excepcion.h"

//typedef int casillero[16];//tipo casillero es un arreglo de tamano 16(4x4)

class CNodo {
public:
    //operaciones o acciones que puedes hacer en cada estado, son cosas enumerables

    enum Operador {
        izquierda,
        derecha,
        arriba,
        abajo
    };

    /**
     * Arreglo de operadores, de tamaño 4.
     */
    static const Operador operadores[];
    static const Operador operadoresInv[];

    CNodo();

    CNodo(const CNodo&); //Copy-Constructor

    /**
     * Construye un CNodo a partir de un Casillero, la accion y el padre que
     * generaron el CNodo, si el padre es NULL el CNodo se interpreta como
     * un estado inicial.
     * @param casillero: Casillero del CNodo, este NO es clonado, por ende
     * cualquier modificacion al Casillero del CNodo afectara al parametro de
     * entrada.
     * @param accion: Accion que junto con el padre genero el CNodo.
     * @param enlace: Padre que junto con la accion genero el Cnodo.
     */
    CNodo(Casillero *casillero, Operador accion, CNodo *padre);


    //void CNodo(const CNodo& orig);
    //destructor
    virtual ~CNodo();

    const Casillero *Casillas() const {
        return casillero;
    }

    /**
     * Apuntador al estado padre, junto con  "OperadorEnlace()" indican que
     * accion sobre cual estado genera al actual.
     * @return CNodo * - Apuntador al tablero padre.
     */
    CNodo* Enlace() const {
        return enlace;
    }

    /**
     * Retorna la accion que genero este estado, junto con  "Enlace()"
     * indican que accion sobre cual estado genera al actual.
     * @return Operador - accion que genero este estado.
     */
    Operador OperadorEnlace() const {
        return operadorEnlace;
    }

    /**
     * Genera el estado sucesor del actual despues de haberse aplicado la
     * operacion indicada.
     * @param oper - Operacion para generar el sucesor.
     * @return Retorna el estado generado por el estado actual y la operacion.
     */
    CNodo *GenerarSucesor(Operador oper);

    /**
     * Funcion que comprueba que un estado CNodo sea estado final
     * @return true si es estado final, de otro modo false.
     */
    bool EsGoal();

    inline CNodo* GetNext() const {
        return next;
    }

    inline void SetNext(CNodo* next) {
        this->next = next;
    }

    inline CNodo* GetPrevious() const {
        return previous;
    }

    inline void SetPrevious(CNodo* previous) {
        this->previous = previous;
    }

    inline void link(CNodo* n) {
        n->next = next;
        if (next)
            next->previous = n;
        next = n;
        n->previous = this;
    }

    inline void unlink() {
        if (next)
            next->previous = previous;
        if (previous)
            previous->next = next;
    }

    unsigned char GetG() const {
        return g;
    }

    void SetG(unsigned char g) {
        this->g = g;
    }

    unsigned char GetH() const {
        return h;
    }

    void SetH(unsigned char h) {
        this->h = h;
    }

    bool IsOpen() const {
        return open;
    }

    void SetOpen(bool open) {
        this->open = open;
    }

    inline unsigned char f() {
        return (g + h);
    }


private:
    Casillero *casillero;
    CNodo *enlace;
    Operador operadorEnlace;
    CNodo* next, *previous; //Para la cola de prioridad
    unsigned char g, h; //Valores de g y h de este CNodo.
    bool open;
};

#endif  /* _CNODO_H_ */
